﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WJP.Domain
{
    /// <summary>
    /// 可观测的对象，实现了<see cref="INotifyPropertyChanging"/>和<see cref="INotifyPropertyChanged"/>接口
    /// </summary>
    [Serializable]
    public abstract class ObservableObject<TPropertyType> : INotifyPropertyChanging, INotifyPropertyChanged, IPropertyObject<TPropertyType>
    {
        private Dictionary<string, TPropertyType> _properties = new Dictionary<string, TPropertyType>();

        #region PropertyChanging

        private PropertyChangingEventHandler _PropertyChangingChangedHandlers;
        /// <summary>
        /// 属性变更前事件
        /// </summary>
        public event PropertyChangingEventHandler PropertyChanging
        {
            add
            {
                _PropertyChangingChangedHandlers += value;
            }
            remove
            {
                _PropertyChangingChangedHandlers -= value;
            }
        }

        /// <summary>
        /// 属性变更前事件
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void OnPropertyChanging(string propertyName)
        {
            if (_PropertyChangingChangedHandlers == null)
                return;
            _PropertyChangingChangedHandlers(this, new PropertyChangingEventArgs(propertyName));
        }

        #endregion

        #region PropertyChanged

        private PropertyChangedEventHandler _PropertyChangedChangedHandlers;
        /// <summary>
        /// 属性变更后事件
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                _PropertyChangedChangedHandlers += value;
            }
            remove
            {
                _PropertyChangedChangedHandlers -= value;
            }
        }

        /// <summary>
        /// 属性变更后事件
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (_PropertyChangedChangedHandlers == null)
                return;
            _PropertyChangedChangedHandlers(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        #region PropertyObject

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        public TPropertyType GetProperty([CallerMemberName] string property = null)
        {
            if (_properties.TryGetValue(property, out TPropertyType obj))
                return obj;
            return default(TPropertyType);
        }

        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="property"></param>
        public void SetProperty(TPropertyType value, [CallerMemberName] string property = null)
        {
            if (Equals(GetProperty(property), value))
                return;
            OnPropertyChanging(property);
            if (value == null)
                _properties.Remove(property);
            else
                _properties[property] = value;
            OnPropertyChanged(property);
        }

        #endregion
    }

    /// <summary>
    /// 可观测的对象，<see cref="ObservableObject{TPropertyType}"/>为<see cref="object"/>类型的简写方式
    /// </summary>
    [Serializable]
    public abstract class ObservableObject : ObservableObject<object>
    {

    }
}
